using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;

using IBatisNet.DataAccess;

using IGlobalist.Cms.Model;

namespace IGlobalist.Cms.DataAccess
{
    /// <summary>
    /// Implenment DAO class
    /// </summary>
    public class DataService
    {
        private static DataService _Instance = new DataService();

        private IDaoManager _DaoManager = null;
        private IClassTypeDAO _ClassTypeDAO = null;
        private IClassDAO _ClassDAO = null;
        private IObjectDAO _ObjectDAO = null;



        private static Hashtable treeObjectCache = new Hashtable();

        private static Hashtable classCache = new Hashtable();
        private static Hashtable listObjectAll = new Hashtable();
 
        /// <summary>
        /// Instance data service
        /// </summary>
        private DataService()
        {
            _DaoManager = ServiceConfig.GetInstance().DaoManager;
            _ClassTypeDAO = (IClassTypeDAO)_DaoManager.GetDao(typeof(IClassTypeDAO));
            _ClassDAO = (IClassDAO)_DaoManager.GetDao(typeof(IClassDAO));
            _ObjectDAO = (IObjectDAO)_DaoManager.GetDao(typeof(IObjectDAO));
        }

        /// <summary>
        /// Get DAO manager
        /// </summary>
        /// <returns>DAO manager</returns>
        public  IDaoManager GetDaoManager(){
            return _DaoManager; 
        }
        /// <summary>
        /// Get DataService
        /// </summary>
        /// <returns>DataService</returns>
        public static DataService GetInstance()
        {
            
            return _Instance;
        }


        #region ClassTypeDAO
        /// <summary>
        /// Get ClassType by id
        /// </summary>
        /// <param name="id">ID of classs</param>
        /// <returns>ClassType object</returns>
        public ICmsClassType GetClassType(short id)
        {
            _DaoManager.OpenConnection();
            ICmsClassType item = _ClassTypeDAO.GetClassType(id);
            _DaoManager.CloseConnection();
            return item;
        }
        /// <summary>
        /// Get Class type list
        /// </summary>
        /// <returns>Class list</returns>
        public IList<ICmsClassType> GetClassTypeList()
        {
            _DaoManager.OpenConnection();
            IList<ICmsClassType> list = _ClassTypeDAO.GetClassTypeList();
            _DaoManager.CloseConnection();
            return list;
        }
        #endregion


        #region ClassDAO
        /// <summary>
        /// Get Class by Id
        /// </summary>
        /// <param name="id">if of class</param>
        /// <returns>Class object</returns>
        public ICmsClass GetClass(long id)
        {
            ICmsClass item = (ICmsClass)classCache["class_" + id];
            if (item == null)
            {
                _DaoManager.OpenConnection();
                item = _ClassDAO.GetClass(id);
                _DaoManager.CloseConnection();
                classCache.Add("class_" + id,item);
            }
            return item;
        }
        /// <summary>
        /// Get class by name
        /// </summary>
        /// <param name="name">Name of class</param>
        /// <returns>Class object</returns>
        public ICmsClass GetClassByName(string name)
        {
            _DaoManager.OpenConnection();
            ICmsClass item = _ClassDAO.GetClassByName(name);
            _DaoManager.CloseConnection();
            return item;
        }  
        /// <summary>
        /// Get class list
        /// </summary>
        /// <returns>Class list</returns>
        public IList<ICmsClass> GetAllClassList()
        {
            _DaoManager.OpenConnection();
            IList<ICmsClass> list = _ClassDAO.GetAllClassList();
            _DaoManager.CloseConnection();
            return list;
        }
       /// <summary>
       /// Get class list by class type id
       /// </summary>
       /// <param name="classTypeID">id of class type</param>
       /// <returns>Clas list</returns>
        public IList<ICmsClass> GetClassListByClassTypeID(short classTypeID)
        {
            _DaoManager.OpenConnection();
            IList<ICmsClass> list = _ClassDAO.GetClassListByClassTypeID(classTypeID);
            _DaoManager.CloseConnection();
            return list;
        }
        /// <summary>
        /// Insert class 
        /// </summary>
        /// <param name="clazz">Class object</param>
        /// <returns>Id of class</returns>
        public long InsertClass(ICmsClass clazz)
        {
            _DaoManager.OpenConnection();
            long id = _ClassDAO.InsertClass(clazz);
            _DaoManager.CloseConnection();
            return id;
        }
        /// <summary>
        /// Update class
        /// </summary>
        /// <param name="clazz">Class object</param>
        public void UpdateClass(ICmsClass clazz)
        {
            _DaoManager.OpenConnection();
            _ClassDAO.UpdateClass(clazz);
            _DaoManager.CloseConnection();
            classCache["class_" + clazz.ID] = clazz;
        }
        /// <summary>
        /// Delete class by id
        /// </summary>
        /// <param name="id">Id of class</param>
        public void DeleteClass(long id)
        {
            _DaoManager.OpenConnection();
            _ClassDAO.DeleteClass(id);
            _DaoManager.CloseConnection();
            classCache.Remove("class_" + id);

        }
       #endregion


        #region ObjectDAO
        /// <summary>
        /// Get object by id
        /// </summary>
        /// <param name="id">Id of object</param>
        /// <returns>CMSObject</returns>
        public ICmsObject GetObject(long id)
        {
            ICmsObject item = (ICmsObject)listObjectAll["obj_" + id];
            if (item == null)
            {
                _DaoManager.OpenConnection();
                item = _ObjectDAO.GetObject(id);
                try
                {
                    listObjectAll.Add("obj_" + id, item);
                }
                catch { }
                _DaoManager.CloseConnection();
            }
            return item;
        }

        /// <summary>
        /// Get CMSObject list by classId
        /// </summary>
        /// <param name="classID">Id of class</param>
        /// <returns>CMSObject object</returns>
        public IList<ICmsObject> GetObjectListByClassID(long classID)
        {
            if (classID == 0) return null;
            _DaoManager.OpenConnection();
            IList<ICmsObject> list = _ObjectDAO.GetObjectListByClassID(classID);
            _DaoManager.CloseConnection();
            return list;
        }

         /// <summary>
        /// Get CMSObject list by name
        /// </summary>
        /// <param name="name">Id of class</param>
        /// <returns>CMSObject object</returns>
        public IList<ICmsObject> GetObjectListAllByName(string name)
        {
            _DaoManager.OpenConnection();
            IList<ICmsObject> list = _ObjectDAO.GetObjectListByname(name);
            _DaoManager.CloseConnection();
            return list;
        }

        

        /// <summary>
        /// Get top CMSObject list by classId
        /// </summary>
        /// <param name="classID">Id of class</param>
        /// <returns>CMSObject list</returns>
        public IList<ICmsObject> GetTopObjectListByClassID(long classID)
        {
            if (classID == 0) return null;
            _DaoManager.OpenConnection();
            IList<ICmsObject> list = _ObjectDAO.GetTopObjectListByClassID(classID);
            _DaoManager.CloseConnection();
            return list;
        }
        /// <summary>
        /// Get top CMSObjcet list by class type id
        /// </summary>
        /// <param name="classTypeID">Id of class type</param>
        /// <returns>CMSObject list</returns>
        public IList<ICmsObject> GetTopObjectListByClassTypeID(short classTypeID)
        {            
            _DaoManager.OpenConnection();
            IList<ICmsObject> list = _ObjectDAO.GetTopObjectListByClassTypeID(classTypeID);
            _DaoManager.CloseConnection();
            return list;
        }

        /// <summary>
        /// Load cache data by classTypeId
        /// </summary>
        /// <param name="classTypeID">Id of class type</param>
        private void LoadCacheData(short classTypeID)
        {
            string key = String.Format("ObjectTree_{0}", classTypeID);
            ICmsObject root = new CmsObject();
            root.Name = "Root";
            root.ID = 0;
            root.SubObjectList = GetTopObjectListByClassTypeID(classTypeID);
            treeObjectCache[key] = root;
        }



        /// <summary>
        /// Clear cache data by classTypeId
        /// </summary>
        /// <param name="classTypeID">Id of class type</param>
        public void ClearCacheData(short classTypeID)
        {
            try{
            string key = String.Format("ObjectTree_{0}", classTypeID);
            treeObjectCache.Remove(key);
            }catch{}
        }
        /// <summary>
        /// Clear cache object by objectId
        /// </summary>
        /// <param name="objectID">Id of object</param>
        public void ClearCacheObject(long objectID)
        {
            try
            {
                ICmsObject obj = GetObject(objectID);
                listObjectAll.Remove("obj_" + objectID);
                listObjectAll.Remove("obj_" + obj.ParentID);
            }
            catch { }
        }
        /// <summary>
        /// Get object list  by classtypeID 
        /// </summary>
        /// <param name="classTypeID">Id of class type</param>
        /// <param name="isReload">Is reload : True/False</param>
        /// <returns>CMSObject</returns>
        public ICmsObject GetObjectListTree(short classTypeID, bool isReload)
        {
            string key = String.Format("ObjectTree_{0}", classTypeID);
            ICmsObject root = (ICmsObject) treeObjectCache[key];
            if (root == null || isReload==true)
            {
                LoadCacheData(classTypeID);
                root = (ICmsObject)treeObjectCache[key];
            }
            return root;
        }

        /// <summary>
        /// Populate object list
        /// </summary>
        /// <param name="parent">CMSObject</param>
        /// <param name="classTypeID">Id of class type</param>
        private void PopulateList(ICmsObject parent, short classTypeID)
        {            
            if (parent.SubObjectList!=null){
                foreach (ICmsObject obj in parent.SubObjectList)
                {     
                    //if (obj.ClassTypeID==classTypeID)
                        PopulateList(obj, classTypeID);                 
                }
            }
        }


        /// <summary>
        /// /Get CMSObject list by version
        /// </summary>
        /// <param name="firstVersionID">Id of version</param>
        /// <returns>CMSObject list</returns>

        public IList<ICmsObject> GetObjectAllVersion(long firstVersionID)
        {
            _DaoManager.OpenConnection();
            IList<ICmsObject> list = _ObjectDAO.GetObjectAllVersion(firstVersionID);
            _DaoManager.CloseConnection();
            return list;
        }

        /// <summary>
        /// Get CMSObject list by classTypeID
        /// </summary>
        /// <param name="classTypeID">Id of class type </param>
        /// <returns>CMSObject list</returns>
        public IList<ICmsObject> GetObjectListAllByClassTypeID(short classTypeID)
        {
            _DaoManager.OpenConnection();
            IList<ICmsObject> list = _ObjectDAO.GetObjectListAllByClassTypeID(classTypeID);
            _DaoManager.CloseConnection();
            return list;
        }

        /// <summary>
        /// Get CMSObject list by test
        /// </summary>
        /// <param name="search">Search string</param>
        /// <returns>CMSObject list</returns>
        public IList<ICmsObject> GetObjectListAllBySearch(string search)
        {
            _DaoManager.OpenConnection();
            IList<ICmsObject> list = _ObjectDAO.GetObjectListAllBySearch(search);
            _DaoManager.CloseConnection();
            return list;
        }
        
         /// <summary>
        /// Get CMSObject list by test
        /// </summary>
        /// <param name="search">Search string</param>
        /// <returns>CMSObject list</returns>
        public IList<ICmsObject> GetObjectListAllByAdvancedSearch(Hashtable search)
        {
            _DaoManager.OpenConnection();
            IList<ICmsObject> list = _ObjectDAO.GetObjectListAllByAdvancedSearch(search);
            _DaoManager.CloseConnection();
            return list;
        }

        
        /// <summary>
        /// Get CMSObject list relate by objectId, classTypeId
        /// </summary>
        /// <param name="relateObjectID">Id of Object</param>
        /// <param name="classTypeID">Id of class type</param>
        /// <returns></returns>
        public IList<ICmsObject> GetObjectListRelateToObjectID(long relateObjectID, short classTypeID)
        {
            _DaoManager.OpenConnection();
            IList<ICmsObject> list = _ObjectDAO.GetObjectListRelateToObjectID(relateObjectID,classTypeID);
            _DaoManager.CloseConnection();
            return list;
        }
        /// <summary>
        /// Insert object
        /// </summary>
        /// <param name="obj">CMSObject object</param>
        /// <returns>Id of CMSObject</returns>
        public long InsertObject(ICmsObject obj)
        {
            _DaoManager.OpenConnection();
            long id = _ObjectDAO.InsertObject(obj);
            if (obj.ParentID > 0)
            {                
                _ObjectDAO.InsertObjectRelation(obj.ParentID, id, obj.ClassTypeID);
            }
            _DaoManager.CloseConnection();
             ClearCacheData(obj.Class.ClassTypeID);
           
            return id;
        }

        /// <summary>
        /// Insert realation CMSObjcet 
        /// </summary>
        /// <param name="id1">Id of CMSObject</param>
        /// <param name="id2">Id of CMSObject</param>
        /// <param name="classTypeID">If of class type</param>
        public void InsertObjectRelation(long id1, long id2, short classTypeID)
        {
            _DaoManager.OpenConnection();
            _ObjectDAO.InsertObjectRelation(id1, id2,classTypeID);
            _DaoManager.CloseConnection();

            ClearCacheData(classTypeID);
            ClearCacheObject(id1);
        }

        /// <summary>
        /// Update relation CMSObject
        /// </summary>
        /// <param name="listOld">Id list old</param>
        /// <param name="listNew">Id list new</param>
        /// <param name="parentID">Id of Object</param>
        /// <param name="classTypID">Id of class type</param>
        public void UpdateObjectRelation(IList<long> listOld,IList<long> listNew, long parentID, short classTypID)
        {
            _DaoManager.OpenConnection();

            foreach (long id in listOld)
            {                
                _ObjectDAO.DeleteObjectOneRelation(parentID, id);                                    
            }

            foreach (long id in listNew)
            {
                _ObjectDAO.InsertObjectRelation(parentID, id, classTypID);             
            }
            _DaoManager.CloseConnection();
        }

        /// <summary>
        /// Update CMSObject
        /// </summary>
        /// <param name="obj">CMSObject object</param>
        public void UpdateObject(ICmsObject obj)
        {
            _DaoManager.OpenConnection();
            ICmsObject objOld = _ObjectDAO.GetObject(obj.ID);

            _ObjectDAO.UpdateObject(obj);            
            if (objOld.ParentID != obj.ParentID)
            {
                _ObjectDAO.DeleteObjectOneRelation(objOld.ParentID, obj.ID);
                if (obj.ParentID > 0)
                {
                    _ObjectDAO.InsertObjectRelation(obj.ParentID, obj.ID, obj.ClassTypeID);
                }
            }

            _DaoManager.CloseConnection();
            ClearCacheData(obj.ClassTypeID);
            ClearCacheObject(objOld.ID);
        }


        
        /// <summary>
        /// Delete CMSObject by Id
        /// </summary>
        /// <param name="id">ID of CMSObject</param>
        public void DeleteObject(long id)
        {
            
            _DaoManager.OpenConnection();
               ICmsObject obj = _ObjectDAO.GetObject(id);
            _ObjectDAO.DeleteObject(id);
            _DaoManager.CloseConnection();
            
            ClearCacheData(obj.ClassTypeID);
            ClearCacheObject(id);
            
           
        }
        /// <summary>
        /// Delete relation CMSObject
        /// </summary>
        /// <param name="id">Id of CMSObject</param>
        public void DeleteObjectRelation(long id)
        {
            _DaoManager.OpenConnection();           
            _ObjectDAO.DeleteObjectRelation(id);
            _DaoManager.CloseConnection();
            ClearCacheObject(id);
        }

       /// <summary>
       /// Delete relation CMSObject and CMSObject
       /// </summary>
       /// <param name="parentID">Id of CMSObject parent</param>
        /// <param name="subID">Id of CMSObject sub</param>
        public void DeleteObjectOneRelation(long parentID, long subID)
        {
            _DaoManager.OpenConnection();
            _ObjectDAO.DeleteObjectOneRelation(parentID, subID);
            _DaoManager.CloseConnection();
            
        }

       /// <summary>
       /// Delete Object by versionId
       /// </summary>
       /// <param name="firstVersionID">Id of version </param>

        public void DeleteObjectAllVersion(long firstVersionID)
        {            
            _DaoManager.OpenConnection();
            _ObjectDAO.DeleteObjectAllVersion(firstVersionID);
            _DaoManager.CloseConnection();
            
        }
        #endregion
    }
}
